"""
Python 基本语法与常用数据结构示例

运行：
  - 使用虚拟环境： .\.venv\Scripts\python python_basics_demo.py
  - 使用系统 Python： python python_basics_demo.py
"""

from __future__ import annotations

import sys
import math
from dataclasses import dataclass
from collections import deque, Counter, namedtuple
import heapq
import io


def title(name: str):
    print("\n" + "=" * 12 + f" {name} " + "=" * 12)


def demo_variables_and_types():
    title("变量与类型")
    a_int = 42
    a_float = 3.14
    a_bool = True
    a_str = "你好，Python"
    a_none = None
    print(type(a_int), a_int)
    print(type(a_float), a_float)
    print(type(a_bool), a_bool)
    print(type(a_str), a_str)
    print(type(a_none), a_none)

    # 多重赋值与解包
    x, y, z = (1, 2, 3)
    print("解包：", x, y, z)
    x, y = y, x
    print("交换：", x, y)


def demo_strings():
    title("字符串")
    s = "Python"
    print("长度：", len(s))
    print("索引：", s[0], s[-1])
    print("切片：", s[1:4], s[:2], s[2:])
    print("拼接：", s + " 是很棒的！")
    print(f"f-string：{s} {2+3}")
    print("方法：", s.upper(), s.lower(), s.startswith("Py"), s.replace("Py", "My"))
    print("分割与合并：", ",".join(["a", "b", "c"]), "a,b,c".split(","))


def demo_lists():
    title("列表 list")
    lst = [3, 1, 4]
    lst.append(2)
    lst.extend([5, 6])
    lst.insert(0, 0)
    print("增改：", lst)
    last = lst.pop()
    lst.remove(4)
    print("删除：", lst, "弹出：", last)
    print("切片：", lst[1:4])
    print("排序：", sorted(lst), "原地排序前：", lst)
    lst.sort(key=lambda n: -n)
    print("原地排序后：", lst)
    squares = [n * n for n in range(6)]
    print("列表推导：", squares)


def demo_tuples():
    title("元组 tuple")
    tup = (1, "a", True)
    print("不可变：", tup)
    a, b, c = tup
    print("解包：", a, b, c)

    Point = namedtuple("Point", ["x", "y"])  # 轻量结构体
    p = Point(3, 4)
    print("namedtuple：", p, p.x, p.y)


def demo_sets():
    title("集合 set")
    s1 = {1, 2, 3}
    s2 = {3, 4, 5}
    s1.add(0)
    s1.discard(2)
    print("集合：", s1)
    print("并集：", s1 | s2, "交集：", s1 & s2, "差集：", s1 - s2)


def demo_dicts():
    title("字典 dict")
    d = {"name": "Alice", "age": 20}
    print("读取：", d["name"], d.get("age"), d.get("missing", "默认"))
    d["age"] = 21
    d.update({"city": "Beijing"})
    print("键值：", list(d.keys()), list(d.values()), list(d.items()))
    inv = {v: k for k, v in d.items()}  # 字典推导
    print("推导：", inv)


def demo_control_flow():
    title("流程控制")
    n = 7
    if n % 2 == 0:
        kind = "偶数"
    elif n % 3 == 0:
        kind = "能被3整除"
    else:
        kind = "其他"
    print("if/elif/else：", kind)

    print("for：", end=" ")
    for i, v in enumerate(["a", "b", "c"], start=1):
        print(f"({i}:{v})", end=" ")
    print()

    print("while：", end=" ")
    c = 0
    while c < 5:
        if c == 3:
            c += 1
            continue
        print(c, end=" ")
        c += 1
    print()

    if sys.version_info >= (3, 10):
        val = "hello"
        match val:
            case 0:
                print("match：数字 0")
            case str() as s if s.startswith("he"):
                print("match：以 he 开头的字符串", s)
            case _:
                print("match：其他")


def demo_functions_and_generators():
    title("函数与生成器")

    def add(a: int, b: int = 1) -> int:
        return a + b

    def show_args(*args, **kwargs):
        print("*args：", args, "**kwargs：", kwargs)

    print("调用：", add(2), add(2, 5))
    show_args(1, 2, 3, name="Alice", age=20)

    # lambda、map、filter
    nums = [1, 2, 3, 4, 5]
    doubled = list(map(lambda x: x * 2, nums))
    even = list(filter(lambda x: x % 2 == 0, nums))
    print("map/filter：", doubled, even)

    # 生成器
    def countdown(n: int):
        while n > 0:
            yield n
            n -= 1

    print("生成器：", list(countdown(5)))


def demo_classes_and_dataclass():
    title("类与 dataclass")

    class Animal:
        def __init__(self, name: str):
            self.name = name

        def speak(self) -> str:
            return "..."

        def __repr__(self) -> str:
            return f"Animal(name={self.name!r})"

    class Dog(Animal):
        def speak(self) -> str:
            return "汪汪"

    a = Animal("动物")
    d = Dog("小黑")
    print("继承与方法：", a, a.speak(), d, d.speak())

    @dataclass
    class User:
        id: int
        name: str
        active: bool = True

    u = User(1, "Alice")
    print("dataclass：", u)


def demo_collections_algo():
    title("常用容器与算法碎片")

    # deque：高效头尾操作
    q = deque([1, 2, 3])
    q.appendleft(0)
    q.append(4)
    print("deque：", list(q))

    # Counter：计数器
    cnt = Counter("abracadabra")
    print("Counter：", cnt.most_common(3))

    # heapq：最小堆
    data = [5, 1, 3, 8, 2]
    heapq.heapify(data)
    smallest = heapq.heappop(data)
    print("heapq：最小值", smallest, "剩余堆", data)


def demo_math_and_rounding():
    title("数学与浮点细节")
    print("四舍五入：", round(2.675, 2))  # 二进制浮点可能非预期
    print("math：", math.sqrt(16), math.isclose(0.1 + 0.2, 0.3))


def demo_io_and_context_manager():
    title("IO 与上下文管理器")

    # 使用 StringIO 演示文件读写接口而不落磁盘
    buf = io.StringIO()
    with buf as f:  # 上下文管理器：自动关闭
        f.write("第一行\n")
        f.write("第二行\n")
    content = buf.getvalue()
    print("写入内容：\n" + content)

    # 演示 with open（注释掉实际写文件）
    # with open("demo.txt", "w", encoding="utf-8") as f:
    #     f.write("Hello, 文件！\n")


def demo_exceptions():
    title("异常处理")
    try:
        x = 1 / 0
    except ZeroDivisionError as e:
        print("捕获异常：", e)
    else:
        print("没有异常时执行")
    finally:
        print("无论是否异常都会执行")

    def safe_div(a, b):
        if b == 0:
            raise ValueError("b 不能为 0")
        return a / b

    try:
        safe_div(1, 0)
    except ValueError as e:
        print("自定义异常：", e)


def main():
    print("Python 版本：", sys.version)
    demo_variables_and_types()
    demo_strings()
    demo_lists()
    demo_tuples()
    demo_sets()
    demo_dicts()
    demo_control_flow()
    demo_functions_and_generators()
    demo_classes_and_dataclass()
    demo_collections_algo()
    demo_math_and_rounding()
    # demo_io_and_context_manager()
    demo_exceptions()


if __name__ == "__main__":
    main()